Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Add in a "verify" slash command to confirm signing keys #912

Closed
wants to merge 8 commits into from

Conversation

kscz
Copy link

@kscz kscz commented May 20, 2017

Allows users to send a text string via an alternative channel (like email
or SMS) which Riot can leverage to confirm that the signing keys match.

Effectively removes the tedium of checking keys until a better mechanism
is completed.

Note that this is dependent on matrix-org/matrix-js-sdk#439

@matrixbot
Copy link
Member

Can one of the admins verify this patch?

@kscz
Copy link
Author

kscz commented May 20, 2017

Ack, messed up the error dialog in my hurry, one moment...

@kscz kscz force-pushed the add_verify branch 2 times, most recently from 9f3b2b5 to 9336642 Compare May 21, 2017 00:20
// Verify a user, device, and pubkey tuple
verify: new Command("verify", "<userId> <deviceId> <deviceSigningKey>", function(room_id, args) {
if (args) {
var matches = args.match(/^(\S+) +(\S+) +(\S+)?$/);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure whether it'd be more sensible to use more specific character groups, since all 3 have specific grammars

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I guess I was trying to avoid having a complex regex considering all the information is checked against APIs which accept arbitrary strings. Is there any reason to make this more specific? Any recommendations?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to go for that path then maybe simpler using String.prototype.split

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW the other code in this file follows this Regex approach to parse out inputs. Probably should be properly validated and sanitized, but that's kinda unrelated to this change.

</div>
),
button: "Accept this validated key",
onFinished: confirm=>{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be onFinished: (confirm) => { to make ESLint happy :)

Copy link
Author

@kscz kscz May 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix! Side note: you should also fix this in onVerifyClick in src/components/views/elements/DeviceVerifyButtons.js

}
}
}
return reject(this.getUsage());
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a trailing comma plox

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

} else {
return reject("WARNING: KEY VALIDATION FAILED! The signing key for " + userId + " and device "
+ deviceId + " is \"" + device.getFingerprint() + "\" which does not match the provided key \""
+ fingerprint + "\" This could mean your communications are being intercepted!");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe toy with template literals to make the string interpolation a little neater

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I'll see if I can clean this up.

@t3chguy
Copy link
Member

t3chguy commented May 21, 2017

Test build deployed to: https://riot.ovh/builds/oob-verify-device/

@t3chguy
Copy link
Member

t3chguy commented May 21, 2017

Seeing Uncaught TypeError: r.promise.done is not a function in console after a verify, seems related

EDIT: fixed

// Verify a user, device, and pubkey tuple
verify: new Command("verify", "<userId> <deviceId> <deviceSigningKey>", function(room_id, args) {
if (args) {
var matches = args.match(/^(\S+) +(\S+) +(\S+)?$/);
Copy link

@midopa midopa May 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the last capture group (for deviceSigningKey) be mandatory? Otherwise, line 299 can get an undefined. And then line 301 would be comparing the device fingerprint against nothing. The call will fail, which is fine. But it seems odd to have a verify method with the actual verifiy datum optional.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh man, how did I miss that?! Yes, sorry, that is a terribly silly bug. Will fix.


var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
return success(Modal.createDialog(QuestionDialog, {
title: "Approve Validated device",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent casing?

Copy link
Author

@kscz kscz May 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sorry, this is a copy-paste induced casing problem. Will drop the 'Q' down to lowercase.
Derp. I mean I will drop the 'V' in "Validated" lowercase

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I meant the title. But yeah that too!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t3chguy requested that the Q in QuestionDialog remains capital to be consistent with other examples in this file (see ErrorDialog line 62, for example)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kscz I think @midopa meant same as me, the V in validated should be lowercase :P

@@ -65,7 +65,8 @@ export default React.createClass({
<ul>
<li><label>Device name:</label> <span>{ this.state.device.getDisplayName() }</span></li>
<li><label>Device ID:</label> <span><code>{ this.state.device.deviceId}</code></span></li>
<li><label>Device key:</label> <span><code><b>{ this.state.device.getFingerprint() }</b></code></span></li>
<li><label>Device fingerprint:</label> <span><code><b>{ this.state.device.getFingerprint() }</b></code></span></li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not against changing this, but we need to keep the Settings screen consistent, so that people know what they are supposed to be comparing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I find it confusing that we have different names for it different places. I'd prefer (in code) if we referred to them as "signing key" and something else (maybe "stream key"?). "Fingerprint" seems to imply that it's a partial key, or something one could use to quickly verify matches, not that it is our primary source of trust for this user.

Would you be opposed to me making a different PR with "fingerprint" replaced by "signing key" or something similar?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pulled this because the refactoring of the verify device dialog made it a difficult merge anyway. I would like to have a longer discussion at some point about the "streaming key" at some point! As I pointed out in our chat a few weeks ago, I'm not terribly clear on why each user+device pairing doesn't have a unique streaming key (currently both keys are basically permanent).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to keep it separate. Sorry for causing conflicts.

I agree that there is a bit of a naming confusion going on at the moment. "Signing key" and "encryption key" might be better terms, though tbh in the UI I would prefer the user to be able to forget there is more than one key.

@@ -65,7 +65,8 @@ export default React.createClass({
<ul>
<li><label>Device name:</label> <span>{ this.state.device.getDisplayName() }</span></li>
<li><label>Device ID:</label> <span><code>{ this.state.device.deviceId}</code></span></li>
<li><label>Device key:</label> <span><code><b>{ this.state.device.getFingerprint() }</b></code></span></li>
<li><label>Device fingerprint:</label> <span><code><b>{ this.state.device.getFingerprint() }</b></code></span></li>
<li><label>Device key:</label> <span><code><b>{ this.state.device.getIdentityKey() }</b></code></span></li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... and I'd prefer not to show this key at all - it's not useful for the verification process and I worry it will confuse people.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it may not be useful at the moment, I wish there was somewhere that it was exposed to the user so they could see the other "public key" they trust. If someone's signing key was used to sign "0" as the streaming key, I would be concerned, and it's just odd that you can't find it in the UI (as far as I can tell).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also removed in the merge.

<li><label>Device name:</label> <span>{ device.getDisplayName() }</span></li>
<li><label>Device ID:</label> <span><code>{ device.deviceId}</code></span></li>
<li><label>Device fingerprint:</label> <span><code><b>{ device.getFingerprint() }</b></code></span></li>
<li><label>Device key:</label> <span><code><b>{ device.getIdentityKey() }</b></code></span></li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, no need for this.

} else {
return reject(`WARNING: KEY VERIFICATION FAILED! The signing key for ${userId} and device
${deviceId} is "${device.getFingerprint()}" which does not match the provided key
"${fingerprint}" This could mean your communications are being intercepted!`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing .

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, yes, good catch.

<div>
<p>
The signing key in your slash command matches the signing key you
received for this user and device!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ! marks make this sound a bit overexcitable ;). Can you just use . please?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok!

... I mean "Ok."

</ul>
</div>
<p>
If you would like to accept this device as verified, press accept!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the text on the button is "Accept this verified key", I think this text is redundant.

description: (
<div>
<p>
The signing key in your slash command matches the signing key you
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit undecided about whether we need a confirmation dialog here. I think that by the time you're pasting /verify commands in, it's up to you to have made sure that they've come from a trustworthy source - I'm not sure what purpose an extra confirmation serves here.

One obvious danger is that inexperienced users might be persuaded to c&p a /verify command from a malicious user. A better solution to that might be to pop up a dialog explaining what's going on the first time they run a /verify command (and store a flag so they don't have to do it each time).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thought was along the lines of future applications: in this flow it's unlikely to matter, but in the future if this was invoked through some other mechanism, I would expect you just want a last-minute "hey, you intended to do this, didn't you?" I was basically assuming "in the future you might invoke this dialog through a QR code, and it shows you what's about to happen before it happens."

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said in #riot-dev: if you haven't invoked this functionality via a slash-command, you may want a confirmation dialog. But in that case, the confirmation functionality doesn't belong in SlashCommands.js.

kscz added 4 commits May 22, 2017 22:03
Allows users to send a text string via an alternative channel (like email
or SMS) which Riot can leverage to confirm that the signing keys match.

Effectively removes the tedium of checking keys until a better mechanism
is completed.

Signed-off-by: Kit Sczudlo <[email protected]>
Replace all instaces of "Validated" with "Verified", and error out
when the user's device is already verified.

Signed-off-by: Kit Sczudlo <[email protected]>
Also remove a few unnecessary escape characters in front or double quotes

Signed-off-by: Kit Sczudlo <[email protected]>
@richvdh
Copy link
Member

richvdh commented May 23, 2017

looks good, thanks!

richvdh added a commit that referenced this pull request May 23, 2017
Allows users to send a text string via an alternative channel (like email
or SMS) which Riot can leverage to confirm that the signing keys match.

Effectively removes the tedium of checking keys until a better mechanism
is completed.

Signed-off-by: Kit Sczudlo <[email protected]>
@richvdh
Copy link
Member

richvdh commented May 23, 2017

merged as 26c8540

@richvdh richvdh closed this May 23, 2017
@kscz kscz deleted the add_verify branch May 23, 2017 09:22
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants